package com.acooly.module.openapi.client.provider.bosc.marshall;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.acooly.core.utils.Reflections;
import com.acooly.core.utils.validate.Validators;
import com.acooly.module.openapi.client.api.exception.ApiClientException;
import com.acooly.module.openapi.client.api.marshal.ApiMarshal;
import com.acooly.module.openapi.client.provider.bosc.BoscConstants;
import com.acooly.module.openapi.client.provider.bosc.BoscProperties;
import com.acooly.module.openapi.client.provider.bosc.annotation.BoscAlias;
import com.acooly.module.openapi.client.provider.bosc.domain.BoscRequestDomain;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;

@Service
public class BoscRequestMarshall extends BoscMarshallSupport implements ApiMarshal<String[], BoscRequestDomain> {

	@Autowired
	private BoscProperties boscProperties;

	@SuppressWarnings("unchecked")
	@Override
	public String[] marshal(BoscRequestDomain source) {
		try {
			Validators.assertJSR303(source);
			String requestJson = null;
			Map<String, String> requestData = Maps.newTreeMap();
			Set<Field> fields = Reflections.getFields(source.getClass());
			String value = null;
			for (Field fieId : fields) {
				BoscAlias boscAlias = fieId.getAnnotation(BoscAlias.class);
				value = convertString(Reflections.invokeGetter(source, fieId.getName()));
				if (null == boscAlias) {// 未设置此注解时，加入请求参数
					requestData.put(fieId.getName(), value);
				} else if (boscAlias.isSign()) {// 如设置了此注解并且属性sign为true，需进行判断
					String aliasValue = boscAlias.value();
					if (null == aliasValue || "".equals(aliasValue)) {// 没有设置注解属性value时即取值字段名
						requestData.put(fieId.getName(), value);
					} else {// 否则取值注解属性value的值
						requestData.put(boscAlias.value(), value);
					}
				}
			}

			if (requestData.size() > 0) {
				requestJson = JSONObject.toJSONString(requestData);
			}

			String signMsg = getSignerFactory().getSigner(BoscConstants.SIGNER_KEY).sign(requestJson, boscProperties);
			String[] signInfo = new String[3];
			signInfo[0] = requestJson;
			JSONObject jsonObject = JSONObject.parseObject(signMsg);
			signInfo[1] = jsonObject.get("signData").toString();
			signInfo[2] = jsonObject.get("signCert").toString();
			return signInfo;
		} catch (Exception e) {
			throw new ApiClientException(e.getMessage());
		}
	}

	private String convertString(Object object) {
		if (object == null) {
			return null;
		}
		return object.toString();
	}

}
